package com.zmn.oms.zmn.aop;

import com.alibaba.fastjson.JSON;
import com.zmn.common.constant.StatusConsts;
import com.zmn.oms.common.annotation.EntrustOrderLog;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.entrust.SyncEntrustOrderStatusDTO;
import com.zmn.oms.model.dto.open.v2.PushOrderDTO;
import com.zmn.oms.model.entity.entrust.EntrustOrder;
import com.zmn.oms.model.entity.log.EntrustOrderSyncLog;
import com.zmn.oms.services.interfaces.entrust.EntrustOrderService;
import com.zmn.oms.services.interfaces.log.EntrustOrderSyncLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Optional;

/**
 * 类描述：委托单日志记录
 *
 * @author lhl
 * @date 2020/01/09 19:01
 */
@Aspect
@Component
@Order(-1)
@Slf4j
public class EntrustOrderLogAspect {

    @Autowired
    private EntrustOrderService entrustOrderService;
    @Autowired
    private EntrustOrderSyncLogService entrustOrderSyncLogService;

    /**
     * 设定切入点
     */
    @Pointcut("@annotation(com.zmn.oms.common.annotation.EntrustOrderLog)")
    private void pointCutMethod() {
    }

    @Around("pointCutMethod() && @annotation(entrustOrderLog)")
    public Object pointCut(ProceedingJoinPoint joinPoint, EntrustOrderLog entrustOrderLog) throws OmsBaseException {

        // 操作类型
        int logType = entrustOrderLog.type();
        boolean beforeProceed = entrustOrderLog.beforeProceed();
        return doLog(joinPoint, logType, beforeProceed);
    }

    /**
     * 记录日志
     * @param joinPoint
     * @param logType
     * @param beforeProceed
     */
    private Object doLog(ProceedingJoinPoint joinPoint, int logType, boolean beforeProceed) throws OmsBaseException {
        PushOrderDTO pushOrderDTO = (PushOrderDTO)joinPoint.getArgs()[0];

        // 创建日志对象
        EntrustOrderSyncLog syncLog = new EntrustOrderSyncLog();
        syncLog.setOperateType(logType);
        syncLog.setBizData(JSON.toJSONString(pushOrderDTO));
        syncLog.setLogRemark(pushOrderDTO.getRemark());

        // 执行业务方法
        ResultDTO<SyncEntrustOrderStatusDTO> resultDTO = null;
        Throwable exception = null;
        try {
            Object proceed = joinPoint.proceed();
            resultDTO = (ResultDTO<SyncEntrustOrderStatusDTO>)proceed;
        } catch (Throwable throwable) {
            exception = throwable;
        }

        // 1. 业务逻辑执行成功，没有报错
        if (resultDTO != null) {
            SyncEntrustOrderStatusDTO syncEntrustOrderStatusDTO = resultDTO.getData();
            EntrustOrder dbEntrustOrder = syncEntrustOrderStatusDTO.getDbEntrustOrder();
            EntrustOrder updateEntrustOrder = syncEntrustOrderStatusDTO.getEntrustOrder();

            syncLog.setEntrustOrderId(dbEntrustOrder.getEntrustId());
            syncLog.setBeforeStatus(dbEntrustOrder.getStatus());
            syncLog.setAfterStatus(Optional.ofNullable(updateEntrustOrder.getStatus()).orElse(dbEntrustOrder.getStatus()));
            syncLog.setResult(resultDTO.getStatus());
            syncLog.setErrorMsg(resultDTO.getMessage());
        }
        // 2. 业务逻辑执行失败（发生了异常）
        else {
            // 设置同步结果为失败
            syncLog.setResult(StatusConsts.STATUS_ERROR);
            syncLog.setErrorMsg(exception.getMessage());

            // 尽量补全日志信息
            try {
                // 获取参数中的委托单ID
                Long orderId = Long.parseLong(pushOrderDTO.getOrderId());
                syncLog.setEntrustOrderId(orderId);

                EntrustOrder entrustOrder = entrustOrderService.findByKey(orderId);
                if (entrustOrder != null) {
                    syncLog.setBeforeStatus(entrustOrder.getStatus());
                    syncLog.setAfterStatus(entrustOrder.getStatus());
                }
            } catch (Exception e) {
            }
        }

        // 保存日志
        try {
            entrustOrderSyncLogService.insertEntrustOrderSyncLog(syncLog);
        } catch (Exception e) {
            log.error("#EntrustOrderLogAspect#doLog# 委托单记录日志失败，PushOrderDTO=[{}]，ErrorMsg=[{}]",
                    JSON.toJSONString(pushOrderDTO), e.getMessage(), e);
        }

        // 继续抛出业务方法发生的异常
        if (exception != null) {
            if (exception instanceof OmsBaseException) {
                throw (OmsBaseException)exception;
            }
            else {
                throw (RuntimeException)exception;
            }
        }
        return resultDTO;
    }
}
